﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HalconDotNet;
using System.Drawing;
using System.Windows.Forms.DataVisualization;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;
//using backprojection;


namespace DCP
{
    public enum Direction { Left, Right, Up, Down, UpLeft, UpRight, DownLeft, DownRight }

    public struct DoublePoint
    {
        public double X;
        public double Y;
    }

    public class FindSpecialContourPoint
    {
        /// <summary>
        /// Richtung zur Boundingbox
        /// </summary>
        
        
        /// <summary>
        /// Gibt true zurück, wenn die x - und y - Koordinate in der übergebenen Region liegt.
        /// </summary>
        /// <param name="region">zu untersuchende Region</param>
        /// <param name="x">X - Koordinate</param>
        /// <param name="y">y  Koordinate</param>
        /// <returns>Liegt Punkt in Region?</returns>
        public bool IsPointInRegion(HObject region, double x, double y)
        {
            HTuple isInside = 0;
            HOperatorSet.TestRegionPoint(region, y, x, out isInside);

            return isInside.I == 0 ? false : true;
        }

        private const double sqrt2 = 1.414213562;

        private List<cellPix> pixels;
        /// <summary>
        /// Liste mit den Konturpixeln
        /// </summary>
        public List<cellPix> Pixels
        {
            get
            {
                return pixels;
            }
            set
            {
                pixels = value;
            }
        }

        private cellSegmentation cellseg;
        /// <summary>
        /// Cell Segmentation Objekt
        /// </summary>
        public cellSegmentation CellSegmentation
        {
            get
            {
                return cellseg;
            }
            set
            {
                cellseg = value;
            }
        }

        public int maxEbenen;

        /// <summary>
        /// Konstruktor. Legt ein neues Objekt der Klasse an.
        /// </summary>
        /// <param name="cellseg">Cell Segmentation Objekt</param>
        /// <param name="pixels">Kontur</param>
        public FindSpecialContourPoint(HTuple window, HObject region, int anzEbenen)
        {
            //Von der übergebenen Region werden die Flächenpunkte sowie Konturpunkte und innere Konturpunkte 
            //(z.B. durch Löcher in den Zellen) ermittelt
            CellSegmentation = new cellSegmentation(window, region);
            //Gibt die Konturpixel zurück
            Pixels = CellSegmentation.getList();
            maxEbenen = anzEbenen;
        }
        public FindSpecialContourPoint(HObject region, int anzEbenen)
        {
            //Von der übergebenen Region werden die Flächenpunkte sowie Konturpunkte und innere Konturpunkte 
            //(z.B. durch Löcher in den Zellen) ermittelt
            CellSegmentation = new cellSegmentation(region);
            //Gibt die Konturpixel zurück
            Pixels = CellSegmentation.getList();
            maxEbenen = anzEbenen;
        }

        /// <summary>
        /// Gibt die gefundenen Maxima zurück.
        /// </summary>
        /// <returns>Schlüssel - Werte - Paar: Position/Pixel</returns>
        public Dictionary<int, cellPix> FindMaxima()
        {
            Dictionary<int, cellPix> outPixels = new Dictionary<int, cellPix>();

            int j;

            int ebene = 0;  //Ebenenzähler
            bool isMax = false;
            for (int i = 0; i < pixels.Count; i++)
            {
                int mittel = 0;
                j = i;
                double dist = pixels[i].distance;   //Aktuelle Entfernung auslesen
                while (true)
                {
                    mittel++;
                    //wenn wahr, wurde ein Anstieg gefunden
                    if (pixels[j].distance > dist)
                    {
                        ebene++;

                        dist = pixels[j].distance;
                    }
                    //vorgegebene Ebene wurde nicht rechtzeitig erreicht
                    else if (pixels[j].distance < dist)
                    {
                        isMax = false; //kein Maximum gefunden
                        ebene = 0;      //Ebenenzähler zurücksetzen...
                        break;          //...Aktuellen Durchlauf abbrechen und von vorne beginnen
                    }
                    if (ebene == maxEbenen)
                    {//vorgegebene Ebene erreicht
                        isMax = true;
                        break;
                    }

                    j++;
                    //ORG
                    //if (j == pixels.Count)
                    //geändert 09.12.10:
                    if (j >= pixels.Count-1)
                    {
                        //geändert 09.12.10:
                        j = pixels.Count - 1;
                        break;
                    }
                }
                if (isMax)
                {
                    while (true)
                    {
                        mittel++;
                        //wahr, wenn auf den Anstieg ein Abstieg folgt
                        if (pixels[j].distance < dist)
                        {//abstieg
                            ebene--;
                            dist = pixels[j].distance;
                        }
                        //nicht bis in vorgegebene Ebene abgestiegen
                        else if (pixels[j].distance > dist)
                        {
                            isMax = false;
                            ebene = 0;
                            break;
                        }
                        if (ebene == 0)
                        {//Erste Ebene wieder erreicht
                            isMax = true;
                            i = j;
                            break;
                        }
                        j++;
                        if (j == pixels.Count)
                        {
                            isMax = false;
                            break;
                        }
                    }
                }

                //if (pixels[i].logicalFunc && isMax)
                if (isMax)
                {
                    if(pixels[i - mittel / 2].logicalFunc)
                        outPixels.Add(i - mittel / 2, pixels[i - mittel / 2]);
                }
            }
            return outPixels;
        }

        /// <summary>
        /// Ermittelt die Distanzen zum rechten Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void RightDirection()
        {
            bool outRegion1, outRegion2, outRegion3;

            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                currentPix.distance = cellseg.X_UR.D - pixels[i].x;

                //+ 2 weil Konturpunkte immer auf den nächsten ganzzahligen Row - & Column - Wert 
                //aufgerundet werden. Es kann sonst passieren, dass Punkte, die eigentlich nicht 
                //mehr in der Region liegen trotzdem als Objektpixel erkannt werden.
                //s. Up, Left, Down

                //currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 2, pixels[i].y);

                outRegion1 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 1, pixels[i].y);
                outRegion2 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 2, pixels[i].y);
                outRegion3 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 3, pixels[i].y);
                if ((outRegion1 == true) && (outRegion2 == true) && (outRegion3 == true))
                    currentPix.logicalFunc = true;
                else
                    currentPix.logicalFunc = false;

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum oberen Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void UpDirection()
        {
            bool outRegion1, outRegion2,outRegion3;

            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                currentPix.distance = pixels[i].y - cellseg.Y_OL;

                outRegion1 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y - 1);
                outRegion2 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y - 2);
                outRegion3 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y - 3);
                if ((outRegion1 == true) && (outRegion2 == true) && (outRegion3 == true))
                    currentPix.logicalFunc = true;
                else
                    currentPix.logicalFunc = false;

                //currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y - 2);
                pixels[i] = currentPix;

            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum unteren Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void DownDirection()
        {
            bool outRegion1, outRegion2, outRegion3;

            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                currentPix.distance = cellseg.Y_UR.D - pixels[i].y;

                outRegion1 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y + 1);
                outRegion2 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y + 2);
                outRegion3 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y + 3);
                if ((outRegion1 == true) && (outRegion2 == true) && (outRegion3 == true))
                    currentPix.logicalFunc = true;
                else
                    currentPix.logicalFunc = false;

                //currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x, pixels[i].y + 2);
                pixels[i] = currentPix;

            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum linken Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void LeftDirection()
        {
            bool outRegion1, outRegion2, outRegion3;

            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                currentPix.distance = pixels[i].x - cellseg.X_OL.D;

                //Die logische Funktion wird auf false gesetzt, falls der linke Pixel teil der Zelle ist
                outRegion1 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 1, pixels[i].y);
                outRegion2 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 2, pixels[i].y);
                outRegion3 = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 3, pixels[i].y);
                if ((outRegion1 == true) && (outRegion2 == true) && (outRegion3 == true))
                    currentPix.logicalFunc = true;
                else
                    currentPix.logicalFunc = false;
                
                //currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 2, pixels[i].y);

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum linken oberen Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void LeftUpDirection()
        {
            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                double dy = pixels[i].y - cellseg.Y_OL.D;
                //double dx = Math.Tan(45 * Math.PI / 180);
                //currentPix.distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                currentPix.distance = sqrt2 * dy;


                currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 2, pixels[i].y - 2);

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum linken oberen Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void RightDownDirection()
        {
            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                double dy = cellseg.X_UR - pixels[i].x;
                
                //double dx = dy / Math.Tan(45 * Math.PI / 180);
                //Da tan(45°) = 1
                //double dx = dy;
                //currentPix.distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                //currentPix.distance = Math.Sqrt(2 * Math.Pow(dy, 2));
                currentPix.distance = sqrt2 * dy;


                currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 2, pixels[i].y + 2);

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum linken oberen Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void LeftDownDirection()
        {
            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                double dy = cellseg.X_UR - pixels[i].x;
                //double dx = Math.Tan(-45 * Math.PI / 180);
                //currentPix.distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                currentPix.distance = sqrt2 * dy;

                currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x - 2, pixels[i].y + 2);

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Distanzen zum linken oberen Rand und trägt diese in die Pixel - Liste ein.
        /// </summary>
        public void RightUpDirection()
        {
            for (int i = 0; i < pixels.Count; i++)
            {
                cellPix currentPix = pixels[i];
                double dy = pixels[i].y - cellseg.Y_OL.D;
                //double dx = Math.Tan(-45 * Math.PI / 180);
                //currentPix.distance = Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));
                currentPix.distance = sqrt2 * dy;

                currentPix.logicalFunc = !IsPointInRegion(cellseg.SelectedArea, pixels[i].x + 2, pixels[i].y - 2);

                pixels[i] = currentPix;
            }
        }

        /// <summary>
        /// Ermittelt die Cs in allen angegebenen Richtungen und gibt eine DoubleList mit den gefundenen Punkten zurück.
        /// </summary>
        /// <param name="dirs">Richtungen</param>
        /// <returns>Liste mit den gefundenen Cs</returns>
        public List<DoublePoint> FindAllMaxima(params object[] dirs)
        {
            Direction[] directions = new Direction[dirs.Length];
            for (int i = 0; i < dirs.Length; i++)
            {
                directions[i] = (Direction) dirs[i];
            }
            Dictionary<int, cellPix> resDict = new Dictionary<int, cellPix>();
           
            //if true, use algorithm in left direction
            if(((Direction[])directions).Contains(Direction.Left))
            {
                // Ermittelt die Distanzen zum linken Rand und trägt diese in die Pixel - Liste ein.
                // Die logische Funktion des Konturpixels wird auf false gesetzt, falls der linke Pixel ein Zellpixel ist
                LeftDirection();
                //Die gefundenen Maxima 
                Dictionary<int,cellPix> res = FindMaxima();
                //Maxima noch einer weiteren Prüfung unterziehen:
                //Für gefundene potentielle Maxima der Richtung links muss der rechte Nachbarpixel ein Zellpixel sein
                Dictionary<int, cellPix> res2 = new Dictionary<int, cellPix>();
                foreach (var key in res.Keys)
                {
                    if ((IsPointInRegion(cellseg.SelectedArea, res[key].x + 1, res[key].y)) && (IsPointInRegion(cellseg.SelectedArea, res[key].x + 2, res[key].y)))
                        res2.Add(key, res[key]);
                }
                foreach (var key in res2.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res2[key]);
                    }
                }
            }
            //if true, use algorithm in right direction
            if (directions.Contains(Direction.Right))
            {
                RightDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                //Maxima noch einer weiteren Prüfung unterziehen:
                //Für gefundene potentielle Maxima der Richtung rechts muss der linke Nachbarpixel ein Zellpixel sein
                Dictionary<int, cellPix> res2 = new Dictionary<int, cellPix>();
                foreach (var key in res.Keys)
                {
                    if ((IsPointInRegion(cellseg.SelectedArea, res[key].x - 1, res[key].y)) && (IsPointInRegion(cellseg.SelectedArea, res[key].x - 2, res[key].y) && (IsPointInRegion(cellseg.SelectedArea, res[key].x - 3, res[key].y))))
                        res2.Add(key, res[key]);
                }
                foreach (var key in res2.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res2[key]);
                    }
                }
            }
            //if true, use algorithm in up direction
            if (directions.Contains(Direction.Up))
            {
                UpDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                //Maxima noch einer weiteren Prüfung unterziehen:
                //Für gefundene potentielle Maxima der Richtung oben muss der untere Nachbarpixel ein Zellpixel sein
                Dictionary<int, cellPix> res2 = new Dictionary<int, cellPix>();
                foreach (var key in res.Keys)
                {
                    if ((IsPointInRegion(cellseg.SelectedArea, res[key].x, res[key].y + 1)) && (IsPointInRegion(cellseg.SelectedArea, res[key].x, res[key].y + 2)))
                        res2.Add(key, res[key]);
                }
                foreach (var key in res2.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res2[key]);
                    }
                }
            }
            //if true, use algorithm in down direction
            if (directions.Contains(Direction.Down))
            {
                DownDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                //Maxima noch einer weiteren Prüfung unterziehen:
                //Für gefundene potentielle Maxima der Richtung unten muss der obere Nachbarpixel ein Zellpixel sein
                Dictionary<int, cellPix> res2 = new Dictionary<int, cellPix>();
                foreach (var key in res.Keys)
                {
                    if ((IsPointInRegion(cellseg.SelectedArea, res[key].x, res[key].y - 1)) && (IsPointInRegion(cellseg.SelectedArea, res[key].x, res[key].y - 2)))
                        res2.Add(key, res[key]);
                }
                foreach (var key in res2.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res2[key]);
                    }
                }
            }
            //if true, use algorithm in up left direction
            if (directions.Contains(Direction.UpLeft))
            {
                LeftUpDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                foreach (var key in res.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res[key]);
                    }
                }
            }
            //if true, use algorithm in up right direction
            if (directions.Contains(Direction.UpRight))
            {
                RightUpDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                foreach (var key in res.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res[key]);
                    }
                }
            }
            //if true, use algorithm in down right direction
            if (directions.Contains(Direction.DownRight))
            {
                RightDownDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                foreach (var key in res.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res[key]);
                    }
                }
            }
            //if true, use algorithm in down left direction
            if (directions.Contains(Direction.DownLeft))
            {
                LeftDownDirection();
                Dictionary<int, cellPix> res = FindMaxima();
                foreach (var key in res.Keys)
                {
                    if (!resDict.Keys.Contains(key))
                    {
                        resDict.Add(key, res[key]);
                    }
                }
            }
            //convert dictionary to result list
            List<DoublePoint> returnList = new List<DoublePoint>();
            foreach (var key in resDict.Keys)
            {
                returnList.Add(new DoublePoint { X = resDict[key].x, Y = resDict[key].y });
            }
            return returnList;
        }


     
        /// <summary>
        /// Zeichnet die Distanzen und die Cs in das übergeben Chart - Control für eine bestimmte Richtung ein.
        /// </summary>
        /// <param name="chart">Chart - Control in das gezeichnet werden soll.</param>
        /// <param name="direction">Richtung, die gezeichnet werden soll.</param>
        public void ShowMaxima(Chart chart, Direction direction)
        {
            switch (direction)
            {
                case Direction.Down:
                    DownDirection();
                    break;
                case Direction.DownLeft:
                    LeftDownDirection();
                    break;
                case Direction.DownRight:
                    RightDownDirection();
                    break;
                case Direction.Left:
                    LeftDirection();
                    break;
                case Direction.Right:
                    RightDirection();
                    break;
                case Direction.Up:
                    UpDirection();
                    break;
                case Direction.UpLeft:
                    LeftUpDirection();
                    break;
                case Direction.UpRight:
                    RightUpDirection();
                    break;
                default:
                    //nothing to do
                    return;
            }
            Dictionary<int, cellPix> maxima = FindMaxima();
            chart.Series.Clear();
            chart.Annotations.Clear();
            chart.Series.Add(new Series(direction.ToString()));
            chart.Series[0].ChartType = SeriesChartType.Line;
            foreach (var p in Pixels)
            {
                chart.Series[0].Points.Add(p.distance);
            }
            foreach (var key in maxima.Keys)
            {
                CalloutAnnotation ann = new CalloutAnnotation();
                ann.AllowMoving = true;

                ann.Text = "C";
                ann.SmartLabelStyle.Enabled = true;
                ann.SmartLabelStyle.IsOverlappedHidden = true;
                chart.Annotations.Add(ann);
                ann.AnchorDataPoint = chart.Series[0].Points[key];
                ann.Visible = true;

            }
        }

    }

    public struct cellPix
    {
        public double x;
        public double y;
        public bool logicalFunc;
        public double distance;
    }

    public class cellSegmentation
    {
        private List<double> contourPixList_cellHoles_Row;
        private List<double> contourPixList_cellHoles_Col;
        private HTuple hv_contourPix_Row;
        private HTuple hv_contourPix_Col;
        private HTuple hv_cellPixel_Row;
        private HTuple hv_cellPixel_Col;
        public HTuple Y_OL, X_OL, Y_UR, X_UR;

        private int smallestRecWidth;
        private int smallestRecHeight;
        public HObject SelectedArea { get; private set; }

        public cellSegmentation(HTuple Window, HObject cellRegion)
        {
            HOperatorSet.SetSystem("do_low_error", "false");
            cellClusterSeg(Window, cellRegion);
        }
        public cellSegmentation(HObject cellRegion)
        {
            HOperatorSet.SetSystem("do_low_error", "false");
            cellClusterSeg(cellRegion);
        }

        private void cellClusterSeg(HObject cellRegion)
        {
            HObject ho_cellContour, FilledSelectedArea, RegionDifference, connectedRegionDifference;
            HObject selectedHoles, hole;
            //HObject dilatedRegion, erodedRegion;
            HOperatorSet.GenEmptyObj(out ho_cellContour);
            HTuple rows, cols;

            contourPixList_cellHoles_Row = new List<double>();
            contourPixList_cellHoles_Col = new List<double>();
            SelectedArea = cellRegion;
            //kl.umschl.Rechteck
            HOperatorSet.SmallestRectangle1(SelectedArea, out Y_OL, out X_OL, out Y_UR, out X_UR);
            smallestRecHeight = System.Math.Abs(Y_UR - Y_OL);
            smallestRecWidth = System.Math.Abs(X_UR - X_OL);

            HOperatorSet.GetRegionPoints(SelectedArea, out hv_cellPixel_Row, out hv_cellPixel_Col);
            ho_cellContour.Dispose();

            HOperatorSet.GetRegionContour(SelectedArea, out hv_contourPix_Row, out hv_contourPix_Col);
            //----------------------------------------------------------------------------------------------
            //Innenkonturen der Zellen durch Löcher etc. bestimmen und Innenkonturpunkte in Listen speichern
            //----------------------------------------------------------------------------------------------
            HOperatorSet.FillUp(SelectedArea, out FilledSelectedArea);
            HOperatorSet.Difference(FilledSelectedArea, SelectedArea, out RegionDifference);
            HOperatorSet.Connection(RegionDifference, out connectedRegionDifference);
            HOperatorSet.SelectShape(connectedRegionDifference, out selectedHoles, "area", "and", 100, 100000);
            if (selectedHoles.CountObj() == 1)
            {
                HOperatorSet.GenContourRegionXld(selectedHoles, out ho_cellContour, "border");
                HOperatorSet.GetContourXld(ho_cellContour, out rows, out cols);
                for (int i = 0; i < rows.Length; i++)
                {
                    contourPixList_cellHoles_Row.Add(rows[i]);
                    contourPixList_cellHoles_Col.Add(cols[i]);
                }
            }
            if (selectedHoles.CountObj() > 1)
            {
                for (int i = 0; i < selectedHoles.CountObj(); i++)
                {
                    HOperatorSet.SelectObj(selectedHoles, out hole, i + 1);
                    HOperatorSet.GenContourRegionXld(hole, out ho_cellContour, "border");
                    HOperatorSet.GetContourXld(ho_cellContour, out rows, out cols);
                    for (int j = 0; j < rows.Length; j++)
                    {
                        contourPixList_cellHoles_Row.Add(rows[j]);
                        contourPixList_cellHoles_Col.Add(cols[j]);
                    }
                }
            }
            ho_cellContour.Dispose();
        }
        private void cellClusterSeg(HTuple Window, HObject cellRegion)
        {
            HObject ho_cellContour, FilledSelectedArea, RegionDifference, connectedRegionDifference;
            HObject selectedHoles, hole;
            HObject dilatedRegion, erodedRegion;
            HOperatorSet.GenEmptyObj(out ho_cellContour);
            HTuple rows, cols;

            contourPixList_cellHoles_Row = new List<double>();
            contourPixList_cellHoles_Col = new List<double>();
            //HOperatorSet.SetLineWidth(Window, 2);
            //HOperatorSet.SetColor(Window, "yellow");
            //HOperatorSet.DispObj(cellRegion, Window);
            //MessageBox.Show("Zellregion für DCP");
            SelectedArea = cellRegion;
            //kl.umschl.Rechteck
            HOperatorSet.SmallestRectangle1(SelectedArea, out Y_OL, out X_OL, out Y_UR, out X_UR);
            smallestRecHeight = System.Math.Abs(Y_UR - Y_OL);
            smallestRecWidth = System.Math.Abs(X_UR - X_OL);

            //HOperatorSet.SetLineWidth(Window, 2);
            //HOperatorSet.SetColor(Window, "red");
            //HOperatorSet.DispObj(cellRegion, Window);
            //HOperatorSet.SetLineWidth(Window, 1);

            //MessageBox.Show("cellRegion");

            //-----------------------------------------------------------------------
            //Testhalber eine Glättung der Region einführen
            //-----------------------------------------------------------------------

            //HOperatorSet.ClosingCircle(SelectedArea, out erodedRegion, 5.5);

            //HOperatorSet.SetLineWidth(Window, 2);
            //HOperatorSet.SetColor(Window, "yellow");
            //HOperatorSet.DispObj(erodedRegion, Window);
            //HOperatorSet.SetLineWidth(Window, 1);

            //MessageBox.Show("geglättete Zellregion");

            HOperatorSet.GetRegionPoints(SelectedArea, out hv_cellPixel_Row, out hv_cellPixel_Col);
            ho_cellContour.Dispose();
            //HOperatorSet.GenContourRegionXld(SelectedArea, out ho_cellContour, "border");
            //HOperatorSet.SetColor(Window, "cyan");
            //HOperatorSet.DispObj(ho_cellContour, Window);
            //MessageBox.Show("Zellkontur für DCP");
            //HOperatorSet.GetContourXld(ho_cellContour, out hv_contourPix_Row, out hv_contourPix_Col);
            HOperatorSet.GetRegionContour(SelectedArea, out hv_contourPix_Row, out hv_contourPix_Col);
            //----------------------------------------------------------------------------------------------
            //Innenkonturen der Zellen durch Löcher etc. bestimmen und Innenkonturpunkte in Listen speichern
            //----------------------------------------------------------------------------------------------
            HOperatorSet.FillUp(SelectedArea, out FilledSelectedArea);
            HOperatorSet.Difference(FilledSelectedArea, SelectedArea, out RegionDifference);
            HOperatorSet.Connection(RegionDifference, out connectedRegionDifference);
            HOperatorSet.SelectShape(connectedRegionDifference, out selectedHoles, "area", "and", 100, 100000);
            if (selectedHoles.CountObj() == 1)
            {
                HOperatorSet.GenContourRegionXld(selectedHoles, out ho_cellContour, "border");
                HOperatorSet.GetContourXld(ho_cellContour, out rows, out cols);
                //HOperatorSet.SetLineWidth(Window, 2);
                //HOperatorSet.SetColor(Window, "cyan");
                //HOperatorSet.DispObj(ho_cellContour, Window);
                //MessageBox.Show("Innere Zellkonturen");
                for (int i = 0; i < rows.Length; i++)
                {
                    contourPixList_cellHoles_Row.Add(rows[i]);
                    contourPixList_cellHoles_Col.Add(cols[i]);
                }
            }
            if (selectedHoles.CountObj() > 1)
            {
                for(int i=0;i<selectedHoles.CountObj();i++)
                {
                    HOperatorSet.SelectObj(selectedHoles, out hole, i + 1);
                    HOperatorSet.GenContourRegionXld(hole, out ho_cellContour, "border");
                    //HOperatorSet.SetLineWidth(Window, 2);
                    //HOperatorSet.SetColor(Window, "cyan");
                    //HOperatorSet.DispObj(ho_cellContour, Window);
                    //MessageBox.Show("Innere Zellkonturen");
                    HOperatorSet.GetContourXld(ho_cellContour, out rows, out cols);
                    for (int j = 0; j < rows.Length; j++)
                    {
                        contourPixList_cellHoles_Row.Add(rows[j]);
                        contourPixList_cellHoles_Col.Add(cols[j]);
                    }
                }             
            }
            ho_cellContour.Dispose();
        }
        //Gibt die Konturpixel zurück
        public List<cellPix> getList()
        {
            List<cellPix> cellList = new List<cellPix>();
            //Warum noch -1 ????
            for (int i = 0; i < hv_contourPix_Col.Length - 1; i++)
            {
                cellPix cp = new cellPix();
                cp.y = hv_contourPix_Row[i];
                cp.x = hv_contourPix_Col[i];
                cellList.Add(cp);
            }
            return cellList;
        }
        public List<DoublePoint> getContourPoints()
        {
            List<DoublePoint> contPointsList = new List<DoublePoint>();
            //Warum noch -1 ????
            for (int i = 0; i < hv_contourPix_Col.Length - 1; i++)
            {
                DoublePoint dpt = new DoublePoint();
                dpt.Y = hv_contourPix_Row[i];
                dpt.X = hv_contourPix_Col[i];
                contPointsList.Add(dpt);
            }
            return contPointsList;
        }
        public List<DoublePoint> getInnerContourPoints()
        {
            List<DoublePoint> contPointsList = new List<DoublePoint>();
            for (int i = 0; i < contourPixList_cellHoles_Row.Count; i++)
            {
                DoublePoint dpt = new DoublePoint();
                dpt.Y = contourPixList_cellHoles_Row[i];
                dpt.X = contourPixList_cellHoles_Col[i];
                contPointsList.Add(dpt);
            }
            return contPointsList;
        }
    }
}
